﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Windows;
using KJSyncXP.Extensions;
using KJSyncXP.Services;
using log4net;

public class FileChangeWatcher
{
    private readonly FileSystemWatcher _watcher;
    private readonly ILog _logger;
    private readonly AppConfig _appConfig;
    private readonly SqliteToFileSyncService _sqliteToFileSyncService;
    private readonly object _lockObj = new object();
    private readonly Dictionary<string, DateTime> _lastProcessedTimes = new Dictionary<string, DateTime>();
    private const int EventThresholdMs = 2000;


    public FileChangeWatcher(AppConfig appConfig,SqliteToFileSyncService sqliteToFileSyncService, ILog logger = null)
    {
        _appConfig = appConfig;
        _logger = logger;
        _sqliteToFileSyncService = sqliteToFileSyncService;

        if (!Directory.Exists(_appConfig.IdFileDataDirectory))
        {
            _logger?.Error($"监听目录不存在：{_appConfig.IdFileDataDirectory}");
            return;
        }

        _watcher = new FileSystemWatcher
        {
            Path = _appConfig.IdFileDataDirectory,
            Filter = "*.id",
            NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size,
            EnableRaisingEvents = true,
            IncludeSubdirectories = false
        };

        _watcher.Changed += OnFileChanged;
        _logger?.Info($"文件监听器已启动，监听目录：{_appConfig.IdFileDataDirectory}");
    }

    private void OnFileChanged(object sender, FileSystemEventArgs e)
    {
        lock (_lockObj)
        {
            string fileName = Path.GetFileName(e.FullPath);
            DateTime now = DateTime.Now;

            // 过滤重复事件
            if (_lastProcessedTimes.TryGetValue(fileName, out DateTime lastTime)
                && (now - lastTime).TotalMilliseconds < EventThresholdMs)
            {
                _logger?.Debug($"忽略重复事件：{fileName}（间隔{(now - lastTime).TotalMilliseconds}ms）");
                return;
            }
            _lastProcessedTimes[fileName] = now;
            Thread.Sleep(200); // 等待文件写入完成

            try
            {
                string lockFilePath = Path.ChangeExtension(e.FullPath, ".lock");
                bool hasLockFile = File.Exists(lockFilePath);

                if (hasLockFile) // 自动修改：仅弹框，不处理备份
                {
                    MessageBox.Show("自动弹框");
                    return;
                }
                else
                {
                    // 手动修改：通过备份文件获取上一次内容
                    var fileNamePrefix = Path.GetFileNameWithoutExtension(fileName);
                    _sqliteToFileSyncService.ManualModifyFile(fileNamePrefix);    
                }


                DeleteLockFile(lockFilePath);
            }
            catch (IOException ex)
            {
                _logger?.Error($"读取/写入文件【{e.FullPath}】失败（可能被占用）", ex);
            }
            catch (Exception ex)
            {
                _logger?.Error($"处理文件【{e.FullPath}】失败", ex);
            }
        }
    }

    #region 辅助方法：安全读写文件
    /// <summary>
    /// 带重试机制的安全读取文件
    /// </summary>
    private string ReadFileSafely(string filePath)
    {
        const int maxRetries = 3;
        const int retryDelay = 100;

        for (int i = 0; i < maxRetries; i++)
        {
            try
            {
                using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                using (var reader = new StreamReader(stream))
                {
                    return reader.ReadToEnd();
                }
            }
            catch (IOException) when (i < maxRetries - 1)
            {
                Thread.Sleep(retryDelay);
            }
        }
        throw new IOException($"多次尝试后仍无法读取文件：{filePath}");
    }

    /// <summary>
    /// 安全写入文件（覆盖现有内容）
    /// </summary>
    private void WriteFileSafely(string filePath, string content)
    {
        const int maxRetries = 3;
        const int retryDelay = 100;

        for (int i = 0; i < maxRetries; i++)
        {
            try
            {
                using (var stream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                using (var writer = new StreamWriter(stream))
                {
                    writer.Write(content);
                    return;
                }
            }
            catch (IOException) when (i < maxRetries - 1)
            {
                Thread.Sleep(retryDelay);
            }
        }
        throw new IOException($"多次尝试后仍无法写入文件：{filePath}");
    }

    /// <summary>
    /// 删除.lock文件
    /// </summary>
    private void DeleteLockFile(string lockFilePath)
    {
        if (File.Exists(lockFilePath))
        {
            try
            {
                File.Delete(lockFilePath);
                _logger?.Info($"已删除.lock文件：{lockFilePath}");
            }
            catch (IOException ex)
            {
                _logger?.Error($"删除.lock文件【{lockFilePath}】失败", ex);
            }
        }
    }
    #endregion

    public void StopWatching()
    {
        _watcher?.Dispose();
        _logger?.Info("文件监听器已停止");
    }
}